﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MarkDownFileSplitter.Meilisearch
{
    /// <summary>
    /// 没有层次的通用解析
    /// </summary>
    internal class DataParser
    {
        protected List<dynamic> m_items;
        public List<dynamic> Items { get { return m_items; } }
        private DataTable m_sourceDataTable;
        private Dictionary<string, string> m_sourceDataTableColumnType;

        public bool AutoGenId { get; internal set; }
        public int StartIdOffset { get; internal set; } = 0; // 新增：起始ID偏移量
        public DataTable SourceDataTable { get => m_sourceDataTable; set => m_sourceDataTable = value; }

        #region 数据来源
        public List<dynamic> Parse(string path)
        {
            SourceDataTable = null;
            m_items = new List<dynamic>();
            // 从文件中读取JSON字符串
            string jsonContent = File.ReadAllText(path);
            JArray root = JsonConvert.DeserializeObject<JArray>(jsonContent);
            // 遍历root对象的所有子元素
            // 如果是数组，遍历数组中的每个元素
            foreach (var item in root)
            {
                m_items.Add(item);
            }
            return m_items;
        }

        public List<dynamic> Parse(JArray jArray)
        {
            SourceDataTable = null;
            m_items = [.. jArray];
            return m_items;
        }
        /// <summary>
        /// 直接使用DataTable
        /// </summary>
        /// <param name="jArray"></param>
        /// <param name="columnTypes"></param>
        /// <returns></returns>
        public List<dynamic> Parse(DataTable jArray, Dictionary<string, string> columnTypes)
        {
            SourceDataTable = jArray;
            m_sourceDataTableColumnType = columnTypes;
            m_items = [.. jArray.Rows];
            return m_items;
        }
        #endregion

        #region 获得列名
        /// <summary>
        /// 获取所有layer项中的属性名称的并集
        /// </summary>
        /// <returns>不重复的属性名称列表</returns>
        public List<string> GetAllPropertyNames()
        {
            if (SourceDataTable == null)
            {
                HashSet<string> propertyNames = new HashSet<string>();

                foreach (var item in m_items)
                {
                    // 将dynamic对象转换为JObject以便遍历其属性
                    JObject jObject = JObject.FromObject(item);

                    // 获取所有属性名并添加到HashSet中
                    foreach (var property in jObject.Properties())
                    {
                        propertyNames.Add(property.Name);
                    }
                }

                // 将HashSet转换为List并返回
                return propertyNames.ToList();
            }
            else
            {
                HashSet<string> propertyNames = new HashSet<string>();
                for (var i = 0; i < SourceDataTable.Columns.Count; i++)
                {
                    propertyNames.Add(SourceDataTable.Columns[i].ColumnName);
                }
                return propertyNames.ToList();
            }
        }
        /// <summary>
        /// 改变列名
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        internal void ChangeColumnName(string v1, string v2)
        {
            if (SourceDataTable == null) return;
            SourceDataTable.Columns[v1].ColumnName = v2;
        }
        #endregion

        #region 转换为JSON方便传输
        public JArray ConvertToJArray(List<string> checkedItems, int fromIndex = 0, int endIndex = -1)
        {
            if (m_sourceDataTable != null)
            {
                JArray result = new JArray();
                if (endIndex == -1 || endIndex >= m_items.Count)
                {
                    endIndex = m_items.Count;
                }
                for (var i = fromIndex; i < endIndex; i++)
                {
                    var item = m_items[i] as DataRow;
                    JObject filteredObj = new JObject();
                    if (checkedItems != null)
                    {
                        foreach (DataColumn prop in m_sourceDataTable.Columns)
                        {
                            if (checkedItems.Contains(prop.ColumnName))
                            {
                                if (item[prop] is DBNull)
                                {
                                    filteredObj.Add(prop.ColumnName, "");
                                }
                                else
                                {
                                    if (m_sourceDataTableColumnType != null && m_sourceDataTableColumnType.ContainsKey(prop.ColumnName.ToLower()))
                                    {
                                        var columnType = m_sourceDataTableColumnType[prop.ColumnName.ToLower()];
                                        var convertedValue = ConvertValueByPostgreSQLType(item[prop], columnType);
                                        filteredObj.Add(prop.ColumnName, JToken.FromObject(convertedValue));
                                    }
                                    else
                                    {
                                        filteredObj.Add(prop.ColumnName, item[prop].ToString());
                                    }
                                }
                            }
                        }
                        if (AutoGenId)
                        {
                            filteredObj.Add("Id", (StartIdOffset + i).ToString()); // 修改：使用偏移量
                        }
                        result.Add(filteredObj);
                    }
                    else
                    {
                        foreach (DataColumn prop in m_sourceDataTable.Columns)
                        {
                            if (item[prop] is DBNull)
                            {
                                filteredObj.Add(prop.ColumnName, "");
                            }
                            else
                            {
                                if (m_sourceDataTableColumnType != null && m_sourceDataTableColumnType.ContainsKey(prop.ColumnName.ToLower()))
                                {
                                    var columnType = m_sourceDataTableColumnType[prop.ColumnName.ToLower()];
                                    var convertedValue = ConvertValueByPostgreSQLType(item[prop], columnType);
                                    filteredObj.Add(prop.ColumnName, JToken.FromObject(convertedValue));
                                }
                                else
                                {
                                    filteredObj.Add(prop.ColumnName, item[prop].ToString());
                                }
                            }
                        }
                        if (AutoGenId)
                        {
                            filteredObj.Add("Id", (StartIdOffset + i).ToString()); // 修改：使用偏移量
                        }
                        result.Add(filteredObj);
                    }
                }
                return result;
            }
            else
            {
                return ConvertToJArrayFromJSON(checkedItems, fromIndex, endIndex);
            }
        }
        /// <summary>
        /// 根据PostgreSQL数据类型转换值为适当的JSON类型
        /// </summary>
        /// <param name="value">原始值</param>
        /// <param name="columnType">PostgreSQL列类型</param>
        /// <returns>转换后的值</returns>
        private object ConvertValueByPostgreSQLType(object value, string columnType)
        {
            if (value == null || value is DBNull)
                return "";

            var valueStr = value.ToString();
            switch (columnType.ToLower())
            {
                case "json":
                case "jsonb":
                    try
                    {
                        return JsonConvert.DeserializeObject(valueStr) as JToken;
                    }
                    catch
                    {
                        return valueStr;
                    }

                case "integer":
                case "int":
                case "int4":
                case "bigint":
                case "int8":
                case "smallint":
                case "int2":
                    if (long.TryParse(valueStr, out long intValue))
                        return intValue;
                    return valueStr;

                case "decimal":
                case "numeric":
                case "real":
                case "float4":
                case "double precision":
                case "float8":
                    if (decimal.TryParse(valueStr, out decimal decimalValue))
                        return decimalValue;
                    return valueStr;

                case "boolean":
                case "bool":
                    if (bool.TryParse(valueStr, out bool boolValue))
                        return boolValue;
                    return valueStr;

                case "timestamp":
                case "timestamptz":
                case "date":
                case "time":
                case "timetz":
                    if (DateTime.TryParse(valueStr, out DateTime dateValue))
                        return dateValue.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
                    return valueStr;

                case "uuid":
                    if (Guid.TryParse(valueStr, out Guid guidValue))
                        return guidValue.ToString();
                    return valueStr;

                case "text[]":
                case "varchar[]":
                case "integer[]":
                case "bigint[]":
                    // PostgreSQL数组类型，通常以{val1,val2,val3}格式存储
                    if (valueStr.StartsWith("{") && valueStr.EndsWith("}"))
                    {
                        var arrayContent = valueStr.Substring(1, valueStr.Length - 2);
                        var arrayItems = arrayContent.Split(',').Select(s => s.Trim()).ToArray();
                        return new JArray(arrayItems);
                    }
                    return valueStr;

                default:
                    // 默认作为字符串处理
                    return valueStr;
            }
        }
        /// <summary>
        /// 将m_layerItems转换为JObject列表
        /// </summary>
        /// <param name="checkedItems">如果为空则说明全部上传</param>
        /// <param name="fromIndex">支持批量上传</param>
        /// <returns>转换后的JObject列表</returns>
        public JArray ConvertToJArrayFromJSON(List<string> checkedItems, int fromIndex = 0, int endIndex = -1)
        {
            JArray result = new JArray();
            if (endIndex == -1 || endIndex >= m_items.Count)
            {
                endIndex = m_items.Count;
            }
            for (var i = fromIndex; i < endIndex; i++)
            {
                var item = m_items[i];
                JObject originalObj = JObject.FromObject(item);
                JObject filteredObj = new JObject();
                if (checkedItems != null)
                {
                    foreach (var prop in originalObj.Properties())
                    {
                        if (checkedItems.Contains(prop.Name))
                        {
                            filteredObj.Add(prop.Name, prop.Value);
                        }
                    }
                    if (AutoGenId)
                    {
                        filteredObj.Add("Id", (StartIdOffset + i).ToString()); // 修改：使用偏移量
                    }
                    result.Add(filteredObj);
                }
                else
                {
                    foreach (var prop in originalObj.Properties())
                    {
                        filteredObj.Add(prop.Name, prop.Value);
                    }
                    if (AutoGenId)
                    {
                        filteredObj.Add("Id", (StartIdOffset + i).ToString()); // 修改：使用偏移量
                    }
                    result.Add(filteredObj);
                }
            }
            return result;
        }
        #endregion
    }
}
